<template>
    <el-card class="industrial-card">
      <!-- 工业风格顶部导航 -->
      <header class="industrial-header">
        <div class="header-left">
          <h1>扫码绑定</h1>
        </div>
        <div class="header-center">
          <p class="industrial-clock">{{ currentTime }}</p>
        </div>
        <div class="header-right">
          <p class="industrial-developer">十四事业部装备中心开发</p>
        </div>
      </header>
  
      <!-- 扫码控制区 -->
      <div class="industrial-control-panel">
        <div class="scan-section">
          <div class="scan-input-group">
            <span class="industrial-label">扫码内容：</span>
            <el-input 
              v-model="scancode" 
              class="industrial-input" 
              placeholder="请扫物料码" 
              disabled 
            />
            <el-select v-model="OpreationCode" placeholder="请选择工位" class="selection-input">
              <el-option v-for="Op in Opreations" :key="Op.value" :value="Op.value" :label="Op.value"></el-option>
            </el-select>
            <!-- <el-select v-model="PMcode" placeholder="请选择工位" class="selection-input">
              <el-option v-for="Order in Orders" :key="Order.value" :value="Order.value" :label="Order.label"></el-option>
            </el-select> -->
          </div>
  
          <div class="serial-control">
            <el-button 
              type="primary" 
              plain 
              class="industrial-button"
              @click="openPort"
            >
              连接串口
            </el-button>
            <el-button 
              type="danger" 
              plain 
              class="industrial-button"
              @click="closePort"
            >
              关闭串口
            </el-button>
            <div class="industrial-status-indicator" :style="serialColor"></div>
          </div>
        </div>
      </div>
  
      <!-- 组件物料信息展示区 -->
      <div>
        <div >
          <el-table 
            :data="stateInfo.AllMaterialBOM" 
            :row-class-name="tableRowClassName"
            style="width: 100%"
            :default-expand-all="true"
            :header-cell-style="{
            background:'#06469f', 
            color:'white',
            fontWeight: 'bold',
            fontSize: '14px'
          }"
          >  
            <el-table-column prop="AssemblyMaterialCode" label="物料编码" width="180" align="center" />        
            <el-table-column prop="AssemblyMaterialName" label="物料名称" width="180" align="center" />
            <el-table-column prop="AssemblyMaterialRegex" label="物料正则" width="180" align="center" />
            
            
            <el-table-column label="物料SN" align="center">  
              <template #default="{ row }">
                <el-input 
                  v-model="row.scannedSN" 
                  :disabled="!!stateInfo.AllBindings[row.AssemblyMaterialCode]"
                  @change="handleSNChange(row)"
                ></el-input>
              </template>
            </el-table-column>  
          </el-table>
        </div>
      </div>

      <!-- 完成按钮 -->
      <div class="submit-section">
        <el-button 
          type="success" 
          class="industrial-button"
        >
         入库进度 ({{ matchedCount }}/{{ stateInfo.AllMaterialBOM.length }})
        </el-button>
      </div>

      <!-- 测试 -->
      <!-- <el-button @click="processScannedSN(scancode)">
            物料SN
      </el-button>
      <el-input v-model="scancode">
      </el-input> -->
     
    </el-card>
</template>
  
<script setup lang="ts" name="扫码绑定">
  import { ref, onMounted, onUnmounted ,reactive, computed,watch} from 'vue';
  import { ElMessage } from 'element-plus';
  import request from '/@/utils/request';
  

  // 当前时间显示
  const currentTime = ref('');
  let timer: number;
  
  const updateTime = () => {
    const now = new Date();
    currentTime.value = now.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    });
  };
  
 const PMcode=ref('');
 const OpreationCode = ref('2-OP3100');
const  Opreations =[
    {value:'2-OP3100',label:'齿轴入箱'},
    {value:'2-OP4280-0',label:'总成绑定'},
];
const  Orders =[
    {value:'3241114004',label:'大速比'},
    {value:'003100027194',label:'小速比'},
]


  onMounted(() => {
    updateTime();
    timer = window.setInterval(updateTime, 1000);
    request({
      url: '/api/BaseInformation/ProductBOM/GetProductBOMByOrder',
      method: 'post',
      data: {
        'PMCode':'003100011594',
        'OperationCode':OpreationCode.value,
      } 
    }).then(res=>{
      stateInfo.AllMaterialBOM = res.map(item => ({
        ...item,
        scannedSN: ''
      }));
    })
  });
  
  onUnmounted(() => {
    clearInterval(timer);
  });
  
  // 产品数据
  const scancode = ref('');

  interface Dictionary {  
    [key: string]: any; // 任何类型的值  
  }

  const stateInfo = reactive({
    AllMaterialBOM: [] as any[], 
    AllBindings: {} as Dictionary
  });

  // 计算属性
  const matchedCount = computed(() => {
    return Object.keys(stateInfo.AllBindings).length;
  });

  const allMaterialsMatched = computed(() => {
    return matchedCount.value === stateInfo.AllMaterialBOM.length;
  });
  
  // 串口相关
  const serialColor = ref('background-color:red');
  const port = ref(null);
  const reader = ref(null);
  const textSN = ref('');
  
  // 处理SN变化
  const handleSNChange = (row: any) => {
    const sn = row.scannedSN.trim();
    if (!sn) return;

    // 检查是否已绑定过
    if (stateInfo.AllBindings[row.AssemblyMaterialCode]) {
      ElMessage.warning(`物料 ${row.AssemblyMaterialCode} 已经绑定过SN: ${stateInfo.AllBindings[row.AssemblyMaterialCode]}`);
      row.scannedSN = '';
      return;
    }

    // 正则匹配
    const regex = new RegExp(row.AssemblyMaterialRegex);
    if (regex.test(sn)) {
      stateInfo.AllBindings[row.AssemblyMaterialCode] = sn;
      ElMessage.success(`物料 ${row.AssemblyMaterialCode} 绑定成功`);
      
      // 检查是否全部完成
      if (allMaterialsMatched.value) {
        ElMessage.success('所有物料已匹配完成，提交入库');
        
      }
    } else {
      ElMessage.error(`SN ${sn} 不符合物料 ${row.AssemblyMaterialCode} 的正则规则`);
      row.scannedSN = '';
    }
  };
  
  // 完成入库
  const completeInventory = async () => {
    try {
    const requestData = {
      MaterialBindings: stateInfo.AllBindings,
      OperatorId: "当前用户ID",  // 从用户系统获取
      WarehouseCode: "默认仓库编码", // 可选项
      MaterialBOM: stateInfo.AllMaterialBOM.map(item => ({
        AssemblyMaterialCode: item.AssemblyMaterialCode,
        AssemblyMaterialName: item.AssemblyMaterialName,
        AssemblyMaterialRegex: item.AssemblyMaterialRegex,
        ScannedSN: stateInfo.AllBindings[item.AssemblyMaterialCode] || null
      })),
    };

      const response = await request({
        url: 'api/ScanMaterialSN/BindOneBatch',
        method: 'post',
        data: {
            MaterialBindings: stateInfo.AllBindings,
            OperatorId: "当前用户ID",  // 从用户系统获取
            WarehouseCode: OpreationCode.value, // 可选项
            MaterialBOM: stateInfo.AllMaterialBOM.map(item => ({
                         AssemblyMaterialCode: item.AssemblyMaterialCode,
                         AssemblyMaterialName: item.AssemblyMaterialName,
                         AssemblyMaterialRegex: item.AssemblyMaterialRegex,
                         ScannedSN: stateInfo.AllBindings[item.AssemblyMaterialCode] || null
            })),
        }
      });

      if (response.Success) {
        ElMessage.success('入库成功');
        // 重置页面
        resetPage();
      } else {
        ElMessage.error(response.message || '入库失败');
      }
    } catch (error) {
      ElMessage.error('入库请求失败');
      console.error(error);
    }
  };

  // 重置页面
  const resetPage = () => {
    stateInfo.AllBindings = {};
    stateInfo.AllMaterialBOM.forEach(item => {
      item.scannedSN = '';
    });
    currentGroup = null;
  };
  
  // 串口操作
  const openPort = async () => {
    try {
      port.value = await navigator.serial.requestPort();
      await port.value.open({ baudRate: 115200 });
    } 
    catch (error) {
      alert("打开串口失败："+error)
    }

    if (port.value && port.value.readable){
      serialColor.value = "background-color:green;width:30px;height:30px";
    }
    else {
      serialColor.value = "background-color:red;width:30px;height:30px";
    }

    await readPort();
  };

  //关闭串口
  const closePort = () => {
    if (reader.value) {
      reader.value.cancel();
    }

    if (port.value) {
      port.value.close();
    }
    
    if (port.value && port.value.readable) {
      serialColor.value = "background-color:green;width:30px;height:30px";
    }
    else {
      serialColor.value = "background-color:red;width:30px;height:30px";
    }
  };

  //读取串口
  const readPort = async () => {
    textSN.value = "";
    if (port.value && port.value.readable) {
      reader.value = port.value.readable.getReader();
      try {
        var flag = true
        while (true) {
          const { value, done } = await reader.value.read();
          if (done) {
            textSN.value = value;
            break;
          }

          for (let i = 0; i < value.length; i++) {
            if(!flag) {
              flag = true
              textSN.value = ''
            }
            textSN.value += String.fromCharCode(value[i]);
            if (value[i] === 13) {
              flag = false
              textSN.value = textSN.value.replace('\r','').replace('\n', '').trim()
              
              // 自动处理扫描到的SN
              if (textSN.value) {
                scancode.value = textSN.value;
                processScannedSN(textSN.value);
              }
            }
          }
        }
      } 
      catch (error) {
        console.error(error);
      } 
      finally {
        if (reader.value) {
          reader.value.releaseLock();
        }
      }
    }
  };

  //判断物料是否为同一速比产品使用


 const materialGroups = [
  {
    name: '大速比',
    allowedParts: ['12905812-00', '12879532-00', '12880376-00'],
    regexes: [
      /^[A-Z0-9]+-12905812-00-[A-Z0-9-]+-[0-9]{4}$/,
      /^[A-Z0-9]+-12879532-00-[A-Z0-9-]+-[0-9]{4}$/,
      /^[A-Z0-9]+-12880376-00-[A-Z0-9-]+-[0-9]{4}$/,
    ],
  },
  {
    name: '小速比',
    allowedParts: ['12906737-00', '12880377-00', '12906229-00'],
    regexes: [
      /^[A-Z0-9]+-12906737-00-[A-Z0-9-]+-[0-9]{4}$/,
      /^[A-Z0-9]+-12880377-00-[A-Z0-9-]+-[0-9]{4}$/,
      /^[A-Z0-9]+-12906229-00-[A-Z0-9-]+-[0-9]{4}$/,
    ],
  },
];


let currentGroup: string | null = null;

const IssameGearType =(barcode: string)=> {
    console.log('type1',currentGroup);
  const groupMatched = materialGroups.find(group =>
    group.regexes.some(regex => regex.test(barcode))
  );
    // console.log('type',groupMatched.name);
  if (!groupMatched) {
    // console.log('type2',groupMatched.name);
    return true;
   
  }

  // 首次扫描，记录当前组
  if (!currentGroup) {
    currentGroup = groupMatched.name;
    // console.log('type3',groupMatched.name);
    return true;

  }

  // 后续扫描需要在同一组
  if (groupMatched.name !== currentGroup) {
    // console.log('type4',groupMatched.name);
    ElMessage.error(`当前扫描属于 ${groupMatched.name}，但您已在扫描 ${currentGroup}，请勿混扫`);
    return false;
  }
  return true;

}


  // 处理扫描到的SN
  const processScannedSN = (sn: string) => {
    let matched = false;
    
    for (const material of stateInfo.AllMaterialBOM) {
      if (stateInfo.AllBindings[material.AssemblyMaterialCode]) continue;
      
      const regex = new RegExp(material.AssemblyMaterialRegex);
      if (regex.test(sn)) {
        if(!IssameGearType(sn))
            return;
        material.scannedSN = sn;
        stateInfo.AllBindings[material.AssemblyMaterialCode] = sn;
        matched = true;
        ElMessage.success(`物料 ${material.AssemblyMaterialCode} 绑定成功`);
        break;
      }
    }
    
    if (!matched) {
      ElMessage.warning(`未找到匹配的物料，或该物料已绑定`);
    }
    
    // 检查是否全部完成
    if (allMaterialsMatched.value) {
      ElMessage.success('所有物料已匹配完成，提交入库');
      completeInventory();
    }
  };

  watch(() => OpreationCode.value, (newValue, oldValue) => {
    request({
      url: '/api/BaseInformation/ProductBOM/GetProductBOMByOrder',
      method: 'post',
      data: {
        'PMCode':'003100011594',
        'OperationCode':OpreationCode.value,
      } 
    }).then(res=>{
      stateInfo.AllMaterialBOM = res.map(item => ({
        ...item,
        scannedSN: ''
      }));
    })
  })

  function tableRowClassName({row}){
    if(stateInfo.AllBindings && stateInfo.AllBindings[row.AssemblyMaterialCode]){
      return 'success-row'
    }
    return 'common-row'
  }
</script>

<style>
  .common-row{
      color: #000 !important;
      text-align: center !important;
      background-color:rgb(202, 189, 189) !important;
      width: 100% !important;
  }
  .success-row{
      color: #000 !important;
      text-align: center !important;
      width: 100%;
      background-color:rgb(52, 173, 30) !important;
      
  }
  .table-UI{
      background:#add8e6 !important;
      border: solid !important;
      border-radius: 0.5px;
  }
 </style>

<style scoped lang="scss">
  /* 工业风格卡片 */
  .industrial-card {
    background-color: #f0f6f4;
    border: 1px solid #6b7a8f;
    border-radius: 4px;
    color: #e0e0e0;
    padding: 16px;
  }
  
  /* 工业风格头部 */
  .industrial-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 20px;
    background-color: #06469f;
    border-bottom: 2px solid #3a4a6b;
    margin-bottom: 20px;
    
    .header-left h1 {
      margin: 0;
      font-size: 22px;
      font-weight: bold;
      color: #e0e0e0;
      letter-spacing: 1px;
    }
    
    .industrial-clock {
      font-family: 'Courier New', monospace;
      font-size: 16px;
      color: #f1f6f8;
    }
    
    .industrial-developer {
      font-size: 14px;
      color: #b0b0b0;
    }
  }
  
  /* 控制面板 */
  .industrial-control-panel {
    background-color: #06469f;
    border: 1px solid #e9d9dc;
    border-radius: 4px;
    padding: 16px;
    margin-bottom: 20px;
  }
  
  .scan-section {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
  }
  
  .scan-input-group {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
  }
  
  .industrial-label {
    font-weight: bold;
    color: #b0b0b0;
    min-width: 60px;
  }
  
  .industrial-input {
    width: 350px;
    
    :deep(.el-input__inner) {
      background-color: #eceff2;
      border: 1px solid #06469f;
      color: #24a4ea;
      border-radius: 2px;
      height: 36px;
      font-family: monospace;
    }
  }
  
  .serial-control {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  
  .industrial-button {
    border-radius: 2px;
    font-weight: 600;
    height: 36px;
    letter-spacing: 0.5px;
  }
  
  .submit-section {
    margin-top: 20px;
    text-align: center;
  }
  
  .el-button {
    &.el-button--primary {
      background-color: #e8eaef;
      color: #0fa0ee;
      &:hover {
        background-color: #e1d8d8;
      }
    }
    &.el-button--warning {
      background-color: #e8eaef;
      color: #e0c410;
      &:hover {
        background-color: #e1d8d8;
      }
    }
    &.el-button--success {
      background-color: #e8eaef;
      color: #67c23a;
      &:hover {
        background-color: #e1d8d8;
      }
    }
  }

  .industrial-status-indicator {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid #6b7a8f;
    box-shadow: 0 0 8px currentColor;
  }
</style>